<template>
  <q-field ref="QYear" v-model="yearVal" :autogrow="false" :class="fieldCls" :disable="disable" :error="!isValid"
           :error-message="placeholder" :readonly="readonly" class="q-field__text" lazy-rules="ondemand" v-bind="$attrs"
           @focus="fieldFocus">
    <template v-slot:control>
      <span v-if="!showText" class="placeholder">{{ placeholder }}</span>
      <QxTooltip v-else>{{ showText }}</QxTooltip>
    </template>
    <template v-slot:append>
      <q-icon v-if="showClearIcon" class="field-clear-icon cursor-pointer" name="cancel"
              @click.stop="handleClear"></q-icon>
      <q-icon name="edit_calendar"></q-icon>
    </template>
    <q-popup-proxy v-model="showPopup" :no-parent-event="readonly || disable" :offset="[0, 5]" anchor="bottom left"
                   breakpoint="0" class="q-year row no-wrap justify-around items-start overflow-hidden" no-focus
                   no-refocus self="top left" transition-hide="jump-up" transition-show="jump-down" @hide="popupBlur">
      <div class="q-year--left-header full-height row items-center">
        <q-btn dense flat icon="chevron_left" round @click="prevPage"></q-btn>
      </div>
      <div class="q-year--view overflow-hidden">
        <transition :name="`q-transition--slide-${moveDir}`">
          <div :key="startYear" class="justify-around row items-center">
            <template v-for="i in 21" :key="i">
              <q-btn :class="yearCls(i)" v-bind="btnBind" @click="updateValue(i)" @mouseenter="onMouseoverEnv">
                {{ startYear + i }}
              </q-btn>
            </template>
          </div>
        </transition>
      </div>
      <div class="q-year--right-header full-height row items-center">
        <q-btn dense flat icon="chevron_right" round @click="nextPage"></q-btn>
      </div>
    </q-popup-proxy>
  </q-field>
</template>

<script setup>
import QxTooltip from 'components/Global/Tools/QxTooltip.vue'
import { getTypeof, isEmpty } from 'src/utils/utils'
import { computed, inject, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'

const YEAR = new Date().getFullYear()

const props = defineProps({
  type: String, disable: Boolean, readonly: Boolean, multiple: Boolean, placeholder: String, option: [Array, Function],
  lazyRules: [Boolean, String], clearable: { type: Boolean, default: true },
  modelValue: [String, Date, Array, Number, Object]
})

const BgToColor = inject('BgToColor')
const emits = defineEmits(['change', 'update:modelValue'])

const QYear = ref(null)
const hoverYear = ref(0)
const isValid = ref(true)
const yearVal = ref(void 0)
const showPopup = ref(false)
const moveDir = ref('right')
const btnBind = reactive({ class: 'col-3', dense: true, flat: true })
const fieldCls = computed(() => showPopup.value ? 'q-field--focused q-field--highlighted' : '')
const yearCls = computed(() => {
  return index => {
    const year = Number(startYear.value) + index
    if (isEmpty(yearVal.value)) return year === YEAR ? 'text-bold text-primary' : ''
    if (getTypeof(yearVal.value) === 'array') {
      if (yearVal.value.includes(year) || yearVal.value.includes(String(year))) {
        return `bg-primary text-bold text-${BgToColor('primary')}`
      }
      return
    }
    if (getTypeof(yearVal.value) === 'object') {
      if (hoverYear.value) {
        const tempYear = Number(yearVal.value.from)
        hoverYear.value = +hoverYear.value
        if (tempYear === year) {
          if (tempYear < hoverYear.value) {
            return 'text-primary q-year__start_hover_year q-year__hover_year q-year__start_year'
          }
          if (tempYear > hoverYear.value) {
            return 'text-primary q-year__end_hover_year q-year__hover_year q-year__end_year'
          }
          return 'text-primary q-year__hover_year'
        }
        if (tempYear < year) {
          if (year < hoverYear.value) return 'text-primary no-border-radius q-year__hover_year'
          if (year === hoverYear.value) return 'text-primary q-year__end_hover_year q-year__hover_year q-year__end_year'
          return
        }
        if (year > hoverYear.value) return 'text-primary no-border-radius q-year__hover_year'
        if (year === hoverYear.value) {
          return 'text-primary q-year__start_hover_year q-year__hover_year q-year__start_year'
        }
        return
      }
      if (yearVal.value.from && yearVal.value.to) {
        const sYear = Number(yearVal.value.from)
        const eYear = Number(yearVal.value.to)
        if (sYear === year && eYear === year) return `bg-primary text-bold text-${BgToColor('primary')}`
        if (sYear === year) return `bg-primary text-bold text-${BgToColor('primary')} q-year__start_year`
        if (eYear === year) return `bg-primary text-bold text-${BgToColor('primary')} q-year__end_year`
        if (year > sYear && year < eYear) return 'no-border-radius q-year__range'
      }
    }
    if (Number(yearVal.value) === year) return `bg-primary text-bold text-${BgToColor('primary')}`
    if (year === YEAR) return 'text-primary text-bold'
  }
})

const formatInitYear = val => val - val % 20 - 1
const startYear = ref(formatInitYear(YEAR))

const range = computed(() => {
  if (props.multiple) return false
  return (props.type || '').includes('range')
})
const showClearIcon = computed(() => {
  const { clearable, disable, readonly } = props
  if (readonly || disable || !clearable) return false
  return !!yearVal.value
})
const showText = computed(() => {
  if (isEmpty(yearVal.value)) return ''
  if (getTypeof(yearVal.value) === 'array') {
    if (!range.value) return yearVal.value.join(', ')
    let str = ''
    for (const el of yearVal.value) str += `${el.from || 'NA'}/${el.to || 'NA'}, `
    return str.slice(0, -2)
  }
  if (getTypeof(yearVal.value) === 'object') return `${yearVal.value.from || 'NA'}/${yearVal.value.to || 'NA'}`
  return yearVal.value
})
const prevPage = () => {
  startYear.value -= 20
  moveDir.value = 'right'
}
const nextPage = () => {
  startYear.value += 20
  moveDir.value = 'left'
}
const initYear = () => {
  if (isEmpty(yearVal.value)) return (startYear.value = formatInitYear(YEAR))
  if (getTypeof(yearVal.value) === 'array') return (startYear.value = formatInitYear(+yearVal.value[0]))
  if (getTypeof(yearVal.value) === 'object') return (startYear.value = formatInitYear(+yearVal.value.from))
  startYear.value = formatInitYear(+yearVal.value)
}
const initValue = () => {
  if (yearVal.value === props.modelValue) return
  if (isEmpty(props.modelValue)) return (yearVal.value = void 0)
  if (getTypeof(props.modelValue) === 'date') return (yearVal.value = props.modelValue.getFullYear())
  yearVal.value = props.modelValue
}

watch(() => props.modelValue, () => initValue(), { immediate: true })

const handleClear = () => {
  yearVal.value = void 0
  showPopup.value = false
  popupBlur()
}
const popupBlur = () => {
  if (range.value && yearVal.value && !yearVal.value.to) yearVal.value = void 0
  emits('update:modelValue', yearVal.value || '')
  if (props.lazyRules === 'ondemand') return
  nextTick(() => {
    if (!QYear.value) return
    QYear.value.blur()
    isValid.value = QYear.value.validate()
  })
}
const fieldFocus = () => initYear()
const onMouseoverEnv = e => {
  if (!range.value) return
  if (isEmpty(yearVal.value)) return
  if (getTypeof(yearVal.value) !== 'object') return
  if (yearVal.value.to) return
  hoverYear.value = +e.target.textContent
}
const updateValue = index => {
  const year = Number(startYear.value) + index
  if (props.multiple) {
    if (isEmpty(yearVal.value)) yearVal.value = [year]
    else yearVal.value.push(year)
    emits('change', yearVal.value, year)
    return
  }
  if (range.value) {
    if (isEmpty(yearVal.value) || yearVal.value.to) {
      hoverYear.value = year
      yearVal.value = { from: year }
      return
    } else {
      if (year < yearVal.value.from) {
        yearVal.value.to = yearVal.value.from
        yearVal.value.from = year
      } else yearVal.value.to = year
      hoverYear.value = 0
      showPopup.value = false
      emits('change', yearVal.value, year)
    }
    return
  }
  yearVal.value = year
  showPopup.value = false
  emits('change', year)
}

const scrollHandle = () => {
  if (!showPopup.value || !QYear.value) return
  const offset = QYear.value.$el.getBoundingClientRect()
  const innerHeight = window.innerHeight
  if (offset.top > innerHeight || offset.bottom < 0) showPopup.value = false
}
const resizeHandle = () => (showPopup.value = false)
onMounted(() => {
  window.addEventListener('scroll', scrollHandle, true)
  window.addEventListener('resize', resizeHandle, false)
})
onBeforeUnmount(() => {
  window.removeEventListener('scroll', scrollHandle, true)
  window.removeEventListener('resize', resizeHandle, false)
})
</script>